/*
 * Copyright (c) 2019. Mikes. All rights reserved.
 *
 * You can contact me with sending email to bWlrZXNfMjAxMkAxNjMuY29t for more information!
 */

package com.climber.android.auth.ui

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.text.method.LinkMovementMethod
import android.view.View
import com.alibaba.android.arouter.facade.Postcard
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.facade.callback.NavCallback
import com.alibaba.android.arouter.launcher.ARouter
import com.climber.android.auth.R
import com.climber.android.auth.api.AuthService
import com.climber.android.auth.api.LoginRequestInfo
import com.climber.android.auth.entity.SocialRegisterCompleteEvent
import com.climber.android.commonres.app.AppAccount
import com.climber.android.commonres.app.service.OTPRequestType
import com.climber.android.commonres.app.service.TokenResponseTransfer
import com.climber.android.commonres.entity.IncUserInfo
import com.climber.android.commonres.helper.onClick
import com.climber.android.commonres.helper.showCountryCodeSpinner
import com.climber.android.commonres.ui.BaseMVPActivity
import com.climber.android.commonsdk.util.NoUnderLineClickSpan
import com.climber.android.commonres.util.UIHelper
import com.climber.android.commonsdk.util.WebLinkClickSpan
import com.climber.android.commonsdk.api.APIError
import com.climber.android.commonsdk.api.ApiObserver
import com.climber.android.commonsdk.api.GlobalErrorProcessor
import com.climber.android.commonsdk.app.AppConstants
import com.climber.android.commonsdk.app.AppDeepLink
import com.climber.android.commonsdk.app.AppEnv
import com.climber.android.commonsdk.arouter.ARouterPathConstants
import com.climber.android.commonsdk.event.BusProvider
import com.climber.android.commonsdk.event.CommonBusEvent
import com.climber.android.commonsdk.helper.openActivityForResult
import com.climber.android.commonsdk.util.APIDataHelper
import com.climber.android.commonsdk.util.PhonePatternUtil
import com.climber.android.lib_share.OneShare
import com.climber.android.lib_share.Platform
import io.ganguo.library.mvp.arouter.ARouterUtils
import io.ganguo.library.mvp.http.RxSchedulers
import io.ganguo.library.mvp.ui.mvp.IPresenter
import io.ganguo.library.mvp.ui.mvp.di.component.AppComponent
import io.ganguo.library.mvp.util.*
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import kotlinx.android.synthetic.main.auth_activity_signin.*
import org.greenrobot.eventbus.Subscribe

/**
 * Created by Mikes at 2019-11-04 15:14
 */
@Route(path = ARouterPathConstants.PATH_SIGN_IN)
class AuthSignInActivity : BaseMVPActivity<IPresenter>() {
    companion object {
        private const val REQUEST_CODE_REGISTER = 100
        private const val REQUEST_CODE_SOCIAL_REGISTER = 101
    }

    /**
     * 登入完成后要跳转的目标路径
     */
    private val postCardPath: String? by lazy {
        if (intent.getStringExtra(AppConstants.PARAM_POSTCARD_PATH) != null) {
            intent.getStringExtra(AppConstants.PARAM_POSTCARD_PATH)
        } else {
            null
        }
    }
    /**
     * 登入完成后要跳转的目标路径需要的参数
     */
    private val postCardBundle: Bundle? by lazy {
        if (intent.getBundleExtra(AppConstants.PARAM_POSTCARD_BUNDLE) != null) {
            intent.getBundleExtra(AppConstants.PARAM_POSTCARD_BUNDLE)
        } else {
            null
        }
    }

    private var choosedCountryCode = AppConstants.DEFAULT_COUNTRY_CODE

    override fun setupActivityComponent(appComponent: AppComponent) {
    }

    override fun getLayoutResourceId(): Int = R.layout.auth_activity_signin

    override fun initView() {
        tv_multi_action.movementMethod = LinkMovementMethod.getInstance()
        tv_multi_action.text = SpanUtils()
                .append("注册账号")
                .setClickSpan(object : NoUnderLineClickSpan() {
                    override fun onClick(widget: View) {
                        openActivityForResult(Intent(this@AuthSignInActivity, AuthSignUpActivity::class.java), REQUEST_CODE_REGISTER)
                    }
                })
                .append("  |  ")
                .append("忘记密码")
                .setClickSpan(object : NoUnderLineClickSpan() {
                    override fun onClick(widget: View) {
                        ARouterUtils.navigationWithDefaultAnim(AppDeepLink.makeDeepLinkUri(ARouterPathConstants.PATH_AUTH_FIND_PASSWORD),
                                ARouterUtils.INVALID_FLAG,
                                null)
                    }
                })
                .create()

        tv_privacy.movementMethod = LinkMovementMethod.getInstance()
        tv_privacy.text = SpanUtils()
                .append("《服务协议》")
                .setForegroundColor(UIUtils.getColor(R.color.common_green))
                .setClickSpan(WebLinkClickSpan(AppEnv.USER_AGREEMENT_URL, preferTitle = "服务协议"))
                .append("和")
                .setForegroundColor(UIUtils.getColor(R.color.common_text_primary))
                .append("《隐私政策》")
                .setForegroundColor(UIUtils.getColor(R.color.common_green))
                .setClickSpan(WebLinkClickSpan(AppEnv.PRIVACY_AGREEMENT_URL, preferTitle = "隐私政策"))
                .create()
    }

    override fun initListener() {
        tv_login_now.onClick {
            val loginRequestInfo = checkLoginWithPassword()

            loginRequestInfo?.let {
                doLoginNow(it)
            }
        }

        accountView.registerLeftViewClick {
            accountView.getLeftTextView().showCountryCodeSpinner(supportFragmentManager) { countryCode ->
                if (countryCode != null) choosedCountryCode = countryCode
            }
        }

        QQLogin.onClick {
            doThirdLogin(Platform.QQ)
        }
        WeChatLogin.onClick {
            doThirdLogin(Platform.Wechat)
        }
        SinaWeiboLogin.onClick {
            doThirdLogin(Platform.SinaWeibo)
        }
    }

    override fun initData() {
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == Activity.RESULT_OK) {
            when (requestCode) {
                REQUEST_CODE_SOCIAL_REGISTER -> {

                }
                REQUEST_CODE_REGISTER -> {
                    // 取出注册的手机号，提醒做一次登录
                    val registerPhone = data?.getStringExtra("result") ?: return
                    accountView.getInputView().setText(registerPhone)
                }
            }
        }
    }

    private fun checkLoginWithPassword(): LoginRequestInfo? {
        val account = accountView.getInputContent()
        val password = passwordView.getInputContent()

        if (TextUtils.isEmpty(account)) {
            ToastHelper.toastMessage(R.string.phone_number_or_nickname_empty)
            return null
        }

        if (StringUtils.isEmpty(password)) {
            ToastHelper.toastMessage(R.string.input_password)
            return null
        }

        return if (PhonePatternUtil.isSupportAreaMobileNumber(choosedCountryCode + account)) {
            LoginRequestInfo.Mobile(choosedCountryCode + account, password)
        } else {
            LoginRequestInfo.Nickname(account, password)
        }
    }

    /**
     * 如果
     * 1. 该社交账号未注册过，需要绑定手机号
     * 2. 该社交账号已注册过，则立即登录
     */
    private fun doThirdLogin(platform: Platform) {
        OneShare.getInstance(this)
                .getAuthorizeAction(platform)
                .doUserInfo {
                    onSuccess {socialParam ->
                        doSocialSignIn(socialParam, platform)
                    }

                    onError { ToastHelper.toastMessage("授权登录失败") }

                    onCancel { ToastHelper.toastMessage("登录已取消") }
                }
    }

    private fun doSocialSignIn(socialParam : Map<String, Any>, platform: Platform) {
        KeyboardUtils.hideSoftInput(this)


        val socialRequest = when(platform){
            Platform.QQ ->{
                LoginRequestInfo.QQ(user_id = socialParam["cc_user_id"].toString(),
                        access_token = socialParam["cc_access_token"].toString(),
                        avatar = socialParam["figureurl_qq"].toString(),
                        nick_name = socialParam["cc_nickname"].toString(),
                        expires_in = APIDataHelper.timestampFor13ByteTo10Byte(socialParam["cc_expire_time"].toString().toLong()).toString())
            }
            Platform.Wechat ->{
                LoginRequestInfo.WeChat(open_id = socialParam["cc_user_id"].toString(),
                        unionid = socialParam["cc_unionid"].toString(),
                        access_token = socialParam["cc_access_token"].toString(),
                        avatar = socialParam["headimgurl"].toString(),
                        nick_name = socialParam["cc_nickname"].toString(),
                        expires_in = APIDataHelper.timestampFor13ByteTo10Byte(socialParam["cc_expire_time"].toString().toLong()).toString())
            }
            Platform.SinaWeibo ->{
                LoginRequestInfo.Sina(user_id = socialParam["cc_user_id"].toString(),
                        access_token = socialParam["cc_access_token"].toString(),
                        avatar = socialParam["avatar_large"].toString(),
                        nick_name = socialParam["cc_nickname"].toString(),
                        expires_in = APIDataHelper.timestampFor13ByteTo10Byte(socialParam["cc_expire_time"].toString().toLong()).toString())
            }
            else -> null
        }
                ?: return

        AuthService.authServiceAPI
                .issueGetLoginToken(APIDataHelper.generateRequestBody(socialRequest.apiParameters()))
                .flatMap { rawResponse ->
                    TokenResponseTransfer().apply(rawResponse)
                }
                .flatMap { tokenResponse ->
                    if (tokenResponse.isSuccessful()) {
                        AuthService.authServiceAPI.issueCheckBindPhoneWithSocialSignIn(APIDataHelper.generateRequestBody(emptyMap()))
                                .flatMap { checkBindPhoneResponse ->
                                    if(checkBindPhoneResponse.isSuccessful()){
                                        AuthService.getUserCardInfoAndWalletInfo()
                                                .map { incUserInfo ->
                                                    incUserInfo.user_id = tokenResponse.data?.user_id

                                                    incUserInfo
                                                }
                                    } else{
                                        Observable.error(APIError.ServerError(errorCode = checkBindPhoneResponse.getServerErrorCode(),
                                                errorMsg = checkBindPhoneResponse.getServerErrorMsg()))
                                    }
                                }
                    } else {
                        Observable.error(APIError.ServerError(errorCode = tokenResponse.getServerErrorCode(),
                                errorMsg = tokenResponse.getServerErrorMsg()))
                    }
                }
                .compose(RxSchedulers.networkRequest())
                .compose(GlobalErrorProcessor.processGlobalError(noticeErrorInfo = true))
                .doOnSubscribe { UIHelper.showLoading(this, null) }
                .subscribeOn(AndroidSchedulers.mainThread())
                .`as`(RxLifecycleUtils.bindLifecycle(this))
                .subscribe(object : ApiObserver<IncUserInfo>() {
                    override fun success(apiResponse: IncUserInfo) {
                        AppAccount.incUserInfo = apiResponse
                        BusProvider.getInstance().post(CommonBusEvent.TokenChangeEvent(authorizated = true))
                        checkAndGoPreviousPostCardPath()
                    }

                    override fun dealError(apiError: APIError) {
                        super.dealError(apiError)
                        UIHelper.hideLoading()

                        if(apiError is APIError.ServerError){
                            when(apiError.errorCode){
                                20001 -> { // 社交登录未绑定手机号
                                    openActivityForResult(Intent(this@AuthSignInActivity, AuthInputPhoneActivity::class.java)
                                            .putExtra("otpRequestType", OTPRequestType.RegisterPhone.name)
                                            .putExtra("socialRequest", socialRequest),
                                            REQUEST_CODE_SOCIAL_REGISTER)
                                }
                            }
                        }
                    }
                })
    }

    private fun doLoginNow(loginRequestInfo: LoginRequestInfo) {
        KeyboardUtils.hideSoftInput(this)
        AuthService.authServiceAPI
                .issueGetLoginToken(APIDataHelper.generateRequestBody(loginRequestInfo.apiParameters()))
                .flatMap { rawResponse ->
                    TokenResponseTransfer().apply(rawResponse)
                }
                .flatMap { tokenResponse ->
                    if (tokenResponse.isSuccessful()) {
                        AuthService.getUserCardInfoAndWalletInfo()
                                .map { incUserInfo ->
                                    incUserInfo.user_id = tokenResponse.data?.user_id

                                    incUserInfo
                                }
                    } else {
                        Observable.error(APIError.ServerError(errorCode = tokenResponse.getServerErrorCode(),
                                errorMsg = tokenResponse.getServerErrorMsg()))
                    }
                }
                .compose(RxSchedulers.networkRequest())
                .compose(GlobalErrorProcessor.processGlobalError(noticeErrorInfo = true))
                .doOnSubscribe { UIHelper.showLoading(this, null) }
                .subscribeOn(AndroidSchedulers.mainThread())
                .`as`(RxLifecycleUtils.bindLifecycle(this))
                .subscribe(object : ApiObserver<IncUserInfo>() {
                    override fun success(apiResponse: IncUserInfo) {
                        AppAccount.incUserInfo = apiResponse
                        BusProvider.getInstance().post(CommonBusEvent.TokenChangeEvent(authorizated = true))
                        checkAndGoPreviousPostCardPath()
                    }

                    override fun dealError(apiError: APIError) {
                        super.dealError(apiError)
                        UIHelper.hideLoading()
                    }
                })
    }

    @Subscribe
    fun receiveSocialRegisterCompleteEvent(event : SocialRegisterCompleteEvent){
        checkAndGoPreviousPostCardPath()
    }

    private fun checkAndGoPreviousPostCardPath() {
        if (postCardPath != null) {
            ARouter.getInstance().build(postCardPath)
                    .with(postCardBundle)
                    .withTransition(R.anim.cbase__slide_in_from_right, R.anim.cbase__slide_out_to_left)
                    .navigation(this@AuthSignInActivity, object : NavCallback() {
                        override fun onArrival(postcard: Postcard?) {
                            this@AuthSignInActivity.finish()
                        }

                        override fun onInterrupt(postcard: Postcard?) {
                            this@AuthSignInActivity.finish()
                        }
                    })
        } else {
            setResult(Activity.RESULT_OK)
            this@AuthSignInActivity.finish()
        }
    }
}